#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/usb.h>

#define USB_VENDOR_ID 0x1234
#define USB_PRODUCT_ID 0x5678

static struct usb_device_id my_usb_table[] = {
    { USB_DEVICE(USB_VENDOR_ID, USB_PRODUCT_ID) },
    {} /* Terminating entry */
};

MODULE_DEVICE_TABLE(usb, my_usb_table);

static int my_usb_probe(struct usb_interface *interface, const struct usb_device_id *id)
{
    struct usb_device *udev = interface_to_usbdev(interface);
    struct usb_device *usb_dev = NULL;
    struct usb_endpoint_descriptor *endpoint;
    struct urb *urb;
    int pipe;
    int status;
    char *data_buffer;
    int buffer_len = 64;

    // Open the device
    usb_dev = usb_get_dev(udev);
    if (!usb_dev) {
        dev_err(&interface->dev, "usb_get_dev failed\n");
        return -ENODEV;
    }

    // Find the bulk-in endpoint
    endpoint = &interface->cur_altsetting->endpoint[0].desc;
    if (!usb_endpoint_is_bulk_in(endpoint)) {
        dev_err(&interface->dev, "No bulk-in endpoint found\n");
        status = -ENODEV;
        goto error;
    }

    // Allocate a data buffer
    data_buffer = kmalloc(buffer_len, GFP_KERNEL);
    if (!data_buffer) {
        dev_err(&interface->dev, "Failed to allocate data buffer\n");
        status = -ENOMEM;
        goto error;
    }

    // Allocate URB
    urb = usb_alloc_urb(0, GFP_KERNEL);
    if (!urb) {
        dev_err(&interface->dev, "Failed to allocate URB\n");
        status = -ENOMEM;
        goto error;
    }

    // Initialize URB
    pipe = usb_rcvbulkpipe(usb_dev, endpoint->bEndpointAddress);
    usb_fill_bulk_urb(urb, usb_dev, pipe, data_buffer, buffer_len, my_usb_callback, NULL);
    urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

    // Submit URB
    status = usb_submit_urb(urb, GFP_KERNEL);
    if (status) {
        dev_err(&interface->dev, "Failed to submit URB: %d\n", status);
        goto error;
    }

    return 0;

error:
    if (urb)
        usb_free_urb(urb);
    if (data_buffer)
        kfree(data_buffer);
    if (usb_dev)
        usb_put_dev(usb_dev);

    return status;
}

static void my_usb_disconnect(struct usb_interface *interface)
{
    // Clean up here if needed
}

static struct usb_driver my_usb_driver = {
    .name = "my_usb_driver",
    .probe = my_usb_probe,
    .disconnect = my_usb_disconnect,
    .id_table = my_usb_table,
};

static int __init my_usb_init(void)
{
    return usb_register(&my_usb_driver);
}

static void __exit my_usb_exit(void)
{
    usb_deregister(&my_usb_driver);
}

module_init(my_usb_init);
module_exit(my_usb_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("Simple USB Device Async URB Driver Example");
